在昨天的文章中,我們提到了可以使用狀態管理套件,把複雜的狀態感變邏輯放到裡頭。今天我們來聊聊狀態管理套件的另一個用途:共享狀態。假設今天 App 有一個 Home 頁面,且在頁面登入之後,需要顯示 User 資訊。
https://dartpad.dev/?id=dc1f03148a17057141d4f75e223459a0
當我們需要再新增其他需要 User 資訊頁面時,很容易的就透過 Route 參數把 User 傳給其他頁面。
https://dartpad.dev/?id=dd76ad4f477465befa9e9b43f61ae259
這種作法有個的缺點:想打開那些需要 User 的頁面時,就需要準備好 User 給他,當大部分的頁面都需要 User 時,User 物件就會在這些頁面之間傳來傳去,使得我們不好管理。
Route 參數跟方法參數一樣,參數越多,我們就越難使用。如同 Clean Code 裡頭提到的,我們應該盡量避免過多的參數。
最理想的參數數量是 0 個,其次是 1 個,再不然是 2 個。
為了解決這個問題,最容易的辦法就是把 User 放到全域變數的層級。
最理想的參數數量是 0 個,其次是 1 個,再不然是 2 個。
為了解決這個問題,最容易的辦法就是把 User 放到全域變數的層級。
https://dartpad.dev/?id=27f3abc9782600bfc6f9dec99395b394
透過全域變數,所有 Screen 或 Widget 都能得知當前 User 的狀態,讓使用 Widget 時,不必再帶 User 參數,使用上會方便許多,但是這種作法有一些缺點:
我們使用狀態管理套件來解決這兩個問題,透過狀態管理套件,我們可以封裝 User 狀態,並開出適當的操作方法讓 Widget 操作,避免 Widget 直接存取 User。而在通知變化的問題上,大多狀態管理套件都有提供 API,讓 Widget 可以在狀態發生變化時,重 build 一次畫面。
https://dartpad.dev/?id=d746a86024f49e27a255932be88f5095
在這邊我們一樣使用 riverpod 修改上面的例子,使用 riverpod 的 watch 方法後,當 User 發生變化時,畫面就會即時的重 build。同樣方式,除了使用 riverpod 以外,使用 Provider、Bloc 等其他狀態管理套件,也能達到一樣的效果,只是寫法上可能不同,但是概念卻是一致的。
原本屬於 StatefulWidget 的狀態,可以透過狀態管理套件,把 scope 提升到更高的層次,藉此讓整個 App 都能使用,又能有效的管理,並且即時根據狀態變換畫面。經過兩天的文章,我們介紹了狀態管理的一些使用情境,但是我們是否能無腦把狀態通通移到狀態管理上呢?明天我們就來討論這個議題。